package com.yylending.las.deviceinfo;

import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.provider.CallLog;
import android.provider.ContactsContract;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import com.yyfax.common.CLog;
import com.yyfax.common.tools.RegularExpress;
import com.yyfax.infrastructure.eventbus.EventAgent;
import com.yyfax.infrastructure.mvp.Model;
import com.yyfax.infrastructure.network.NetworkHelper;
import com.yyfax.infrastructure.network.entity.BaseResultEntity;
import com.yylending.las.Global;
import com.yylending.las.common.AESEntity;
import com.yylending.las.Constants;
import com.yylending.las.common.utils.TimeUtils;
import retrofit2.http.Body;
import retrofit2.http.Header;
import retrofit2.http.POST;
import rx.Observable;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by laixj on 2016/11/22.
 * Copyright © 2016 www.yyfax.com. All Rights Reserved.
 */
public class UploadDeviceModel extends Model {

	private static final String TAG = "UploadDeviceModel";

	public final static int METHOD_UPLOAD_SMS = 0;
	public final static int METHOD_UPLOAD_APP_INFO = 1;
	public final static int METHOD_UPLOAD_CALL_LOG = 2;
	public final static int METHOD_UPLOAD_CONTACT = 3;

	@Override
	public Observable getObservable(Object params, int functionalCode) {
		Service service = (Service) NetworkHelper.createService(Service.class);
		switch (functionalCode) {
			case METHOD_UPLOAD_SMS:
				return service.uploadSms(Global.LOGIN_TOKEN, (AESEntity) params);
			case METHOD_UPLOAD_APP_INFO:
				return service.uploadAppInfo(Global.LOGIN_TOKEN, (AESEntity) params);
			case METHOD_UPLOAD_CALL_LOG:
				return service.uploadCallLog(Global.LOGIN_TOKEN, (AESEntity) params);
			case METHOD_UPLOAD_CONTACT:
				return service.uploadContact(Global.LOGIN_TOKEN, (AESEntity) params);
		}
		return null;
	}

	@Override
	public void onNext(Object obj) {
		CLog.i(TAG, "onNext: " + obj.toString());
		BaseResultEntity result = cast(obj);
		switch (result.requestCode) {
			case METHOD_UPLOAD_SMS:
				UploadSmsResult smsResult = cast(obj);
				EventAgent.post(smsResult);
				break;
			case METHOD_UPLOAD_APP_INFO:
				UploadAppInfoResult appInfoResult = cast(obj);
				EventAgent.post(appInfoResult);
				break;
			case METHOD_UPLOAD_CALL_LOG:
				UploadCallLogResult callLogResult = cast(obj);
				EventAgent.post(callLogResult);
				break;
			case METHOD_UPLOAD_CONTACT:
				UploadContactResult contactResult = cast(obj);
				EventAgent.post(contactResult);
				break;
		}
	}

	private interface Service {
		@POST("server/innerEval/toEval")
		Observable<UploadAppInfoResult> uploadAppInfo(@Header("token") String token, @Body AESEntity params);

		@POST("server/innerEval/toEval")
		Observable<UploadSmsResult> uploadSms(@Header("token") String token, @Body AESEntity params);

		@POST("server/innerEval/toEval")
		Observable<UploadContactResult> uploadContact(@Header("token") String token, @Body AESEntity params);

		@POST("server/innerEval/toEval")
		Observable<UploadCallLogResult> uploadCallLog(@Header("token") String token, @Body AESEntity params);
	}

	static class UploadAppInfoResult extends BaseResultEntity<RuleResult> {
	}

	static class UploadSmsResult extends BaseResultEntity<RuleResult> {
	}

	static class UploadContactResult extends BaseResultEntity<RuleResult> {
	}

	static class UploadCallLogResult extends BaseResultEntity<RuleResult> {
	}

	static class RuleResult {
		public String msg;
	}

	/**
	 * 上传短信Param
	 */
	public static class UploadSms {
		public String evalPath = Constants.EVALPATH_SMS;
		/**
		 * 经度
		 */
		public String longitude;
		/**
		 * 纬度
		 */
		public String latitude;
		public List<SmsInfo> smsInfoList;

		public UploadSms(String longitude, String latitude, List<SmsInfo> smsInfoList) {
			this.longitude = longitude;
			this.latitude = latitude;
			this.smsInfoList = smsInfoList;
		}
	}

	/**
	 * 上传App信息Param
	 */
	public static class UploadApp {
		public String evalPath = Constants.EVALPATH_SOFTWARE;
		/**
		 * 经度
		 */
		public String longitude;
		/**
		 * 纬度
		 */
		public String latitude;
		public List<AppInfo> softwareList;

		public UploadApp(String longitude, String latitude, List<AppInfo> softwareList) {
			this.longitude = longitude;
			this.latitude = latitude;
			this.softwareList = softwareList;
		}
	}

	/**
	 * 上传通话记录Param
	 */
	public static class UploadCallLog {
		public String evalPath = Constants.EVALPATH_CALL;
		/**
		 * 经度
		 */
		public String longitude;
		/**
		 * 纬度
		 */
		public String latitude;
		public List<CallLogs> callRecordList;

		public UploadCallLog(String longitude, String latitude, List<CallLogs> callRecordList) {
			this.longitude = longitude;
			this.latitude = latitude;
			this.callRecordList = callRecordList;
		}
	}

	/**
	 * 上传通讯录信息Param
	 */
	public static class UploadContact {
		public String evalPath = Constants.EVALPATH_CONTACT;
		/**
		 * 经度
		 */
		public String longitude;
		/**
		 * 纬度
		 */
		public String latitude;
		public List<ContactInfo> contactList;

		public UploadContact(String longitude, String latitude, List<ContactInfo> contactList) {
			this.longitude = longitude;
			this.latitude = latitude;
			this.contactList = contactList;
		}
	}

	/**
	 * 读取通讯录
	 */
	public static List<ContactInfo> getContacts(Context context) {
		List<ContactInfo> list = new ArrayList<>();
		Cursor cursor = null;
		try {
			cursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
			if (cursor != null && cursor.moveToFirst()) {
				do {
					//读取通讯录的姓名
					String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
					//读取通讯录的号码
					String phone = formatPhoneNumber(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
					if (RegularExpress.existExpression(name)) {
						//过滤emoj表情
						name = RegularExpress.filterEmoji(name);
					}
					ContactInfo phoneInfo = new ContactInfo(name, phone);
					CLog.i(TAG, "联系人=" + phoneInfo.toString());
					list.add(phoneInfo);
				} while (cursor.moveToNext());
			}
		} catch (Exception e) {
			CLog.i(TAG, "获取联系人异常=" + e.toString());
		} finally {
			if (null != cursor && !cursor.isClosed()) {
				cursor.close();
			}
		}
		return list;
	}

	/**
	 * 获取所有app信息
	 */
	public static List<AppInfo> getAppInfo(Context context) {
		PackageManager pm = context.getPackageManager();
		List<PackageInfo> packInfo = pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);// | PackageManager.GET_PERMISSIONS
		List<AppInfo> appInfoList = new ArrayList<>();
		try {
			for (PackageInfo info : packInfo) {
				ApplicationInfo applicationInfo = info.applicationInfo;
				if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) <= 0) {
					AppInfo appInfo = new AppInfo();
					appInfo.name = applicationInfo.loadLabel(pm).toString();//pm.getApplicationLabel(applicationInfo).toString();
					appInfo.packageName = info.packageName;
					appInfo.installTime = TimeUtils.getTime(info.firstInstallTime);
					CLog.i(TAG, "软件信息=" + appInfo.toString());
					appInfoList.add(appInfo);
				}
			}
		} catch (Exception e) {
			CLog.i(TAG, "获取软件信息异常=" + e.toString());
		}
		return appInfoList;
	}

	/**
	 * 获取通话记录
	 */
	public static List<CallLogs> getCallLogs(Context context) {
		List<CallLogs> callLogList = new ArrayList<>();
		Cursor cursor = null;
		try {
			cursor = context.getContentResolver().query(CallLog.Calls.CONTENT_URI, // 查询通话记录的URI
					new String[]{CallLog.Calls.CACHED_NAME// 通话记录的联系人
							, CallLog.Calls.NUMBER// 通话记录的电话号码
							, CallLog.Calls.DATE// 通话记录的日期
							, CallLog.Calls.DURATION// 通话时长
							, CallLog.Calls.TYPE}// 通话类型
					, null, null, CallLog.Calls.DEFAULT_SORT_ORDER// 按照时间逆序排列，最近打的最先显示
			);
			if (cursor != null && cursor.getCount() > 0) {
				BigDecimal dividend = new BigDecimal(60);
				for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
					CallLogs callLog = new CallLogs();
					String callNumber = formatPhoneNumber(cursor.getString(1));
					//通话类型
					int callType = Integer.parseInt(cursor.getString(4));
					String myPhone = getPhoneNumber(context);
					switch (callType) {
						case CallLog.Calls.MISSED_TYPE:
						case CallLog.Calls.INCOMING_TYPE:
							callLog.callee = myPhone;
							callLog.caller = callNumber;
							callLog.type = "called";
							break;
						case CallLog.Calls.OUTGOING_TYPE:
							callLog.callee = callNumber;
							callLog.caller = myPhone;
							callLog.type = "call";
							break;
					}
					//拨打时间
					long startTime = cursor.getLong(2);
					long duration = cursor.getLong(3);
					long endTime = startTime + duration * 1000;
					callLog.startTime = TimeUtils.getTime(startTime);
					callLog.endTime = TimeUtils.getTime(endTime);
					BigDecimal decimal = new BigDecimal(duration);
					if (duration == 0) {
						callLog.duration = "0";
					} else {
						callLog.duration = decimal.divide(dividend, 2, BigDecimal.ROUND_HALF_UP).doubleValue() + "";
					}
					if(!TextUtils.isEmpty(callLog.type)){
						CLog.i(TAG, "通话记录=" + callLog.toString());
						callLogList.add(callLog);
					}
				}
			}
		} catch (SecurityException ex) {
			CLog.i(TAG, "获取通话记录报错-11->" + ex.getMessage());
		} catch (Exception ex) {
			CLog.i(TAG, "获取通话记录报错-->" + ex.getMessage());
		} finally {
			if (null != cursor && !cursor.isClosed()) {
				cursor.close();
			}
		}
		return callLogList;
	}

	/**
	 * 获取所有短信
	 */
	public static List<SmsInfo> getSmsInfo(Context context) {
		List<SmsInfo> smsList = new ArrayList<>();
		final String SMS_URI_ALL = "content://sms/";
		Cursor cur = null;
		try {
			ContentResolver cr = context.getContentResolver();
			String[] projection = new String[]{"_id", "address", "person", "body", "date", "type"};
			Uri uri = Uri.parse(SMS_URI_ALL);
			cur = cr.query(uri, projection, null, null, "date desc");
			String myPhone = getPhoneNumber(context);
			if (cur != null && cur.moveToFirst()) {
				String phoneNumber;
				String smsBody;
				String date;
				int phoneNumberColumn = cur.getColumnIndex("address");
				int smsBodyColumn = cur.getColumnIndex("body");
				int dateColumn = cur.getColumnIndex("date");
				int typeColumn = cur.getColumnIndex("type");
				do {
					phoneNumber = formatPhoneNumber(cur.getString(phoneNumberColumn));
					smsBody = cur.getString(smsBodyColumn);
					if (RegularExpress.existExpression(smsBody)) {
						//过滤emoj表情
						smsBody = RegularExpress.filterEmoji(smsBody);
					}
					date = TimeUtils.getTime(cur.getLong(dateColumn));
					SmsInfo smsInfo = new SmsInfo();
					smsInfo.content = smsBody;
					smsInfo.sendTime = date;
					int typeId = cur.getInt(typeColumn);
					if (typeId == 1) {//接收
						smsInfo.type = "receive";
						smsInfo.receiver = myPhone;
						smsInfo.sender = phoneNumber;
					} else if (typeId == 2) {//发送
						smsInfo.type = "send";
						smsInfo.receiver = phoneNumber;
						smsInfo.sender = myPhone;
					} else {
						smsInfo.type = "send";
						smsInfo.receiver = phoneNumber;
						smsInfo.sender = myPhone;
					}
					CLog.i(TAG, "短信=" + smsInfo.toString());
					smsList.add(smsInfo);
				} while (cur.moveToNext());
			}
		} catch (Exception ex) {
			CLog.i(TAG, ex.getMessage());
		} finally {
			if (null != cur && !cur.isClosed()) {
				cur.close();
			}
		}
		return smsList;
	}

	/**
	 * 获取本机号码
	 */
	private static String getPhoneNumber(Context context) {
		String phoneNumber = "";
		try {
			TelephonyManager mTelephonyMgr;
			mTelephonyMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
			phoneNumber = formatPhoneNumber(mTelephonyMgr.getLine1Number());
			CLog.i(TAG, "获取本机号码成功=" + phoneNumber);
		} catch (Exception e) {
			CLog.i(TAG, "获取本机号码失败=" + e.getMessage());
		}
		return phoneNumber;
	}

	private static String formatPhoneNumber(String phoneNumber){
		if(TextUtils.isEmpty(phoneNumber)){
			return "";
		}
		return phoneNumber.replace("+86", "").replaceAll("-", "").replaceAll(" ", "");
	}

	public static class AppInfo {
		/**
		 * 软件包名
		 */
		public String packageName;
		/**
		 * 软件名称
		 */
		public String name;
		/**
		 * 安装时间
		 */
		public String installTime;

		@Override
		public String toString() {
			return "AppInfo{" +
					"packageName='" + packageName + '\'' +
					", name='" + name + '\'' +
					", installTime='" + installTime + '\'' +
					'}';
		}
	}

	public static class CallLogs {
		/**
		 * 主叫
		 */
		public String caller;
		/**
		 * 被叫
		 */
		public String callee;
		/**
		 * 通话类型
		 */
		public String type;
		/**
		 * 通话开始时间
		 */
		public String startTime;
		/**
		 * 通话结束时间
		 */
		public String endTime;
		/**
		 * 通话时长
		 */
		public String duration;

		@Override
		public String toString() {
			return "CallLogs{" +
					"caller='" + caller + '\'' +
					", callee='" + callee + '\'' +
					", type='" + type + '\'' +
					", startTime='" + startTime + '\'' +
					", endTime='" + endTime + '\'' +
					", duration='" + duration + '\'' +
					'}';
		}
	}

	public static class ContactInfo {
		/**
		 * 联系人号码
		 */
		private String phone;
		/**
		 * 联系人姓名
		 */
		private String name;

		public ContactInfo(String name, String phone) {
			this.phone = phone;
			this.name = name;
		}

		@Override
		public String toString() {
			return "ContactInfo{" +
					"phone='" + phone + '\'' +
					", name='" + name + '\'' +
					'}';
		}
	}

	public static class SmsInfo {
		/**
		 * content : 短信内容
		 * sender : 15235258546
		 * sendTime : 2016-09-22 18:22:13
		 * receiver : 15236824745
		 */
		/**
		 * 短信内容
		 */
		public String content;
		/**
		 * 发送人
		 */
		public String sender;
		/**
		 * 发送时间
		 */
		public String sendTime;
		/**
		 * 接收人
		 */
		public String receiver;
		/**
		 * 类型（send：发送；receive：接收）
		 */
		public String type;

		@Override
		public String toString() {
			return "SmsInfo{" +
					"content='" + content + '\'' +
					", sender='" + sender + '\'' +
					", sendTime='" + sendTime + '\'' +
					", receiver='" + receiver + '\'' +
					", type='" + type + '\'' +
					'}';
		}
	}
}